package org.barbershop.krpc;

import javassist.*;
import org.barbershop.krpc.util.KConfig;
import org.barbershop.krpc.util.KException;
import org.barbershop.krpc.util.StringUtil;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.barbershop.krpc.util.KConst;

/**
 * 容器类
 * 方法全静态
 */
public class KContext {

    private static Map<Class,Object> clientMap = new HashMap<>();
    private static Map<String,Object> serverMap = new HashMap<>();
    private static KConfig kConfig;

    /**
     * 初始化，根据配置文件扫描RPC接口、注册信息等...
     */
    public static void init(String filePath) throws IOException, ClassNotFoundException,
            IllegalAccessException, InstantiationException, NotFoundException, CannotCompileException {
        kConfig = new KConfig(filePath);

        if (true){
            initServer();
        }

        if (true){
            initClient();
        }
    }

    private static void initServer() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        findSubClass();
        register();
    }

    private static void register(){

    }

    private static void findSubClass() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        List<String> list = kConfig.getServerList();
        for(String className : list){
            Class clazz = KContext.class.getClass().getClassLoader().loadClass(className);
            String subClassName = clazz.getSimpleName();
            if (StringUtil.isNotEmpty(subClassName)){
                Class subClazz = KContext.class.getClass().getClassLoader().loadClass(subClassName);
                Object instance = subClazz.newInstance();
                serverMap.put(className,instance);
            }
        }
    }

    private static void initClient() throws NotFoundException, CannotCompileException, IllegalAccessException, InstantiationException {
        List<String> list = kConfig.getClientList();
        for(String className : list){
            ClassPool pool = ClassPool.getDefault();
            CtClass ctClass = pool.get(className);

            CtClass subCtClass = pool.makeClass(className + KConst.CLASS_SUFFIX);
            subCtClass.setInterfaces(new CtClass[]{ctClass});
            CtMethod ctMethod = rewriteMethod(subCtClass);
            subCtClass.addMethod(ctMethod);

            Class clazz = ctClass.toClass();
            Class subClazz = subCtClass.toClass();
            Object instance = subClazz.newInstance();
            clientMap.put(clazz,instance);
        }
    }

    private static CtMethod rewriteMethod(CtClass subCtClass) throws CannotCompileException {
        //todo rpc
        return CtMethod.make("",subCtClass);
    }

    /**
     * 获取RPC接口实例
     * @param clazz
     * @return
     */
    public static Object getInstanceByClass(Class clazz){
        if(null == clazz){
            throw new KException("Null class");
        }

        if(!clientMap.containsKey(clazz)){
            throw new KException("No class:" + clazz.getName());
        }

        return clientMap.get(clazz);
    }
}
